﻿#pragma once
#ifndef _CR_TR1_STRING_
#define _CR_TR1_STRING_

#include "crmacors.h"
NS_CR_BEGIN

template<class _Elem> struct vl_char_traits
{	// properties of a string or stream unknown element
};

template<> struct vl_char_traits<char>
{
	static INLINE int ct_vscprintf(const char* _Format, va_list _ArgList)
	{
		return _vscprintf(_Format, _ArgList);
	}

	static INLINE int ct_vscprintf_s(char * _DstBuf, size_t _SizeInBytes, const char* _Format, va_list _ArgList)
	{
		return vsprintf_s(_DstBuf, _SizeInBytes, _Format, _ArgList);
	}

	static INLINE int ct_mstr_len(const char* _Source, const char* def_local)
	{
		return strlen(_Source);
	}

	static INLINE int ct_to_mstr(char* _DstBuf, size_t _SizeInBytes, const char* _Source, const char* def_local)
	{
#if defined(_MSC_VER) && _MSC_VER > 1400 
		strcpy_s(_DstBuf, _SizeInBytes, _Source);
#else
		strcpy(_DstBuf, _Source);
#endif
		return strlen(_Source);
	}

	static INLINE int ct_wstr_len(const char* _Source, const char* def_local)
	{
		setlocale(LC_ALL, def_local);
		int len = strlen(_Source) * 2 + 1;

		wchar_t * _DstBuf = new wchar_t[len];
#if defined(_MSC_VER) && _MSC_VER > 1400 
		size_t n = 0;
		mbstowcs_s(&n, _DstBuf, len, _Source, _TRUNCATE);
#else
		int n = mbstowcs(_DstBuf, _Source, len);
#endif
		setlocale(LC_ALL, "");
		delete[] _DstBuf;
		return n;
	}

	static INLINE int ct_to_wstr(wchar_t* _DstBuf, size_t _SizeInBytes, const char* _Source, const char* def_local)
	{
		setlocale(LC_ALL, def_local);
#if defined(_MSC_VER) && _MSC_VER > 1400 
		size_t n = 0;
		mbstowcs_s(&n, _DstBuf, _SizeInBytes, _Source, _TRUNCATE);
#else
		int n = mbstowcs(_DstBuf, _Source, _SizeInBytes);
#endif
		setlocale(LC_ALL, "");
		return n;
	}
};

template<> struct vl_char_traits<wchar_t>
{
	static INLINE int ct_vscprintf(const wchar_t* _Format, va_list _ArgList)
	{
		return _vscwprintf(_Format, _ArgList);
	}

	static INLINE int ct_vscprintf_s(wchar_t* _DstBuf, size_t _SizeInBytes, const wchar_t* _Format, va_list _ArgList)
	{
		return vswprintf_s(_DstBuf, _SizeInBytes, _Format, _ArgList);
	}

	static INLINE int ct_mstr_len(const wchar_t* _Source, const char* def_local)
	{
		setlocale(LC_ALL, def_local);
		int len = wcslen(_Source) * 2 + 1;
		char * _DstBuf = new char[len];

#if defined(_MSC_VER) && _MSC_VER > 1400 
		size_t n = 0;
		wcstombs_s(&n, _DstBuf, len, _Source, _TRUNCATE);
#else
		int n = wcstombs(_DstBuf, _Source, len);
#endif
		setlocale(LC_ALL, "");
		delete[] _DstBuf;
		return n;
	}

	static INLINE int ct_to_mstr(char* _DstBuf, size_t _SizeInBytes, const wchar_t* _Source, const char* def_local)
	{
		setlocale(LC_ALL, def_local);
#if defined(_MSC_VER) && _MSC_VER > 1400 
		size_t n = 0;
		wcstombs_s(&n, _DstBuf, _SizeInBytes, _Source, _TRUNCATE);
#else
		int n = wcstombs(_DstBuf, _Source, _SizeInBytes);
#endif
		setlocale(LC_ALL, "");
		return n;
	}

	static INLINE int ct_wstr_len(const wchar_t* _Source, const char* def_local)
	{
		return wcslen(_Source);
	}

	static INLINE int ct_to_wstr(wchar_t* _DstBuf, size_t _SizeInBytes, const wchar_t* _Source, const char* def_local)
	{
#if defined(_MSC_VER) && _MSC_VER > 1400 
		wcscpy_s(_DstBuf, _SizeInBytes, _Source);
#else
		wcscpy(_DstBuf, _Source);
#endif
		return wcslen(_Source);
	}
};

static _STD ios_base::fmtflags base_flag(int base)
{
	return (base == 16) ? (::std::ios_base::hex) :
		((base == 8) ? (::std::ios_base::oct) : (::std::ios_base::dec));
}

template<class _Elem, class _Traits, class _Alloc, class Type>
Type conver_to_number(::std::basic_stringstream<_Elem, _Traits, _Alloc>& ss, Type t, int base)
{
	ss.setf(base_flag(base));
	ss >> t;
	return t;
}

template<class _Elem, class _Traits, class _Alloc, class Type>
float conver_to_number(::std::basic_stringstream<_Elem, _Traits, _Alloc>& ss, float t, int base)
{
	ss >> t;
	return t;
}

template<class _Elem, class _Traits, class _Alloc, class Type>
double conver_to_number(::std::basic_stringstream<_Elem, _Traits, _Alloc>& ss, double t, int base)
{
	ss >> t;
	return t;
}

template<class _Elem, class _Traits, class _Ax, class _ExTraits>
class base_string
	: public _STD basic_string <_Elem, _Traits, _Ax>
{
	using _Myt = base_string<_Elem, _Traits, _Ax, _ExTraits>;
	using _MyBase = _STD basic_string<_Elem, _Traits, _Ax>;

	using _M_String = base_string<char, ::std::char_traits<char>, ::std::allocator<char>, vl_char_traits<char>>;
	using _W_String = base_string<wchar_t, ::std::char_traits<wchar_t>, ::std::allocator<wchar_t>, vl_char_traits<wchar_t>>;

private:
	mutable int32_t _hash = 0;
public:
	explicit INLINE _Myt(const _Ax& al = _Ax())
		: _MyBase(al)
	{}

	INLINE _Myt(const _Myt& rhs)
		: _MyBase(rhs)
	{}

	INLINE _Myt(const _Myt& rhs, size_type pos, size_type n, const _Ax& al = _Ax())
		: _MyBase(rhs, pos, n, al)
	{}

	INLINE _Myt(const _Elem *s, size_type n, const _Ax& al = _Ax())
		: _MyBase(s, n, al)
	{}

	INLINE _Myt(const _Elem s)
		: _MyBase(1, s)
	{}

	INLINE _Myt(const _Elem *s, const _Ax& al = _Ax())
		: _MyBase(s, al)
	{}

	INLINE _Myt(size_type n, _Elem c, const _Ax& al = _Ax())
		: _MyBase(n, c, al)
	{}

	INLINE _Myt(const_iterator first, const_iterator last, const _Ax& al = _Ax())
		: _MyBase(first, last, al)
	{}

	INLINE _Myt(const _MyBase& base)
		: _MyBase(base)
	{}

	base_string& operator=(const _Elem * const _Ptr)
	{
		_MyBase::operator=(_Ptr);
		return *this;
	}

	base_string& operator=(const base_string& _Right)
	{
		_MyBase::operator=(_Right);
		return *this;
	}

	base_string& operator=(const _MyBase& _Right)
	{
		_MyBase::operator=(_Right);
		return (*this);
	}

	//所有字符转为大写，改变自身  
	_Myt& to_upper()
	{
		transform(begin(), end(), begin(), toupper);
		return *this;
	}

	//所有字符转为大写，不改变自身  
	_Myt to_upper() const
	{
		_Myt s;
		transform(begin(), end(), s.begin(), toupper);
		return s;
	}

	//所有字符转为小写，改变自身  
	_Myt& to_lower()
	{
		transform(begin(), end(), begin(), tolower);
		return *this;
	}

	//所有字符转为小写，不改变自身  
	_Myt to_lower() const
	{
		base_string s;
		transform(begin(), end(), s.begin(), tolower);
		return s;
	}

	//替换字符串
	_Myt& relpace(const _Myt& target, const _Myt& replacement)
	{
		if (target.empty())
			return *this;
		size_type idx;
		while (idx = find(target) != npos)
			_MyBase::replace(idx, target.size(), replacement);
		return *this;
	}

	//删除左边所有包含在target中的字符
	_Myt& trim_left(const _Myt& target)
	{
		while (!empty() && (target.find(*begin()) != npos))
			erase(begin());
		return *this;
	}

	//删除右边所有包含在target中的字符
	_Myt& trim_right(const _Myt& target)
	{
		while (!empty() && (target.find(*rbegin()) != npos))
			erase(--end());
		return *this;
	}

	//返回左边count个字符，count大于总长度则返回整个字符串
	_Myt& left(size_type count) const
	{
		return substr(0, count);
	}

	//返回右边count个字符，count大于总长度则返回整个字符串  
	_Myt& right(size_type count) const
	{
		return substr(_Mysize < count ? 0 : _Mysize - count);
	}

	//忽略大小写判断两个字符串是否相等  
	int compare_no_case(const _Myt& rhs) const
	{
		return to_lower().compare(rhs.to_lower());
	}

	//判断字符串是否以制定字符串开头  
	bool begin_with(const _Myt& rhs) const
	{
		return find(rhs) == size_type(0);
	}

	//判断字符串是否以制定字符串结尾  
	bool end_with(const _Myt& rhs) const
	{
		if (rhs.size() > _Mysize)
			return false;
		return compare(_Mysize - rhs.size(), rhs.size(), rhs) == 0;
	}

	//转换为窄字节
	_M_String mstr(const char * local = "chs") const
	{
		_STD string s("");
		if (_Mysize <= 0)
			return s;
		int len = _ExTraits::ct_mstr_len(_Myptr(), local);
		if (len <= 0)
			return s;

		s.reserve(len);
		_ExTraits::ct_to_mstr(s._Myptr(), len, _Myptr(), local);
		return s.c_str();
	}

	//转换为宽字节
	_W_String wstr(const char * local = "chs") const
	{
		_STD wstring s(L"");
		if (size() <= 0)
			return s;
		int len = _ExTraits::ct_wstr_len(_Myptr(), local);
		if (len <= 0)
			return s;

		s.reserve(len);
		_ExTraits::ct_to_wstr(s._Myptr(), len, _Myptr(), local);
		return s.c_str();
	}

#if _UNICODE
	_W_String tstr() const
	{
		return wstr();
	}
#else
	_M_String tstr() const
	{
		return mstr();
	}
#endif
	
	_STD vector<base_string> split(const _Elem c_sep = _Elem(','))
	{
		return split(base_string(c_sep));
	}

	_STD vector<base_string> split(const base_string& sep = _Elem(","))
	{
		_STD vector<base_string> vec = {};

		if (!this->empty())
		{
			base_string tmp;
			size_type pos_begin = this->find_first_not_of(sep);
			size_type pos_common = 0;

			while (pos_begin != base_string::npos)
			{
				pos_common = this->find(sep, pos_begin);
				if (pos_common != base_string::npos)
				{
					tmp = this->substr(pos_begin, pos_common - pos_begin);
					pos_begin = pos_common + sep.length();
				}
				else
				{
					tmp = this->substr(pos_begin);
					pos_begin = pos_common;
				}

				if (!tmp.empty())
				{
					vec.push_back(tmp);
					tmp.clear();
				}
			}
		}

		return vec;
	}

	//生成HashCode
	int32_t hash_code() const
	{
		int h = _hash;
		if (h == 0 && this->length() > 0)
		{
			for (uint32_t i = 0; i < _Mysize; ++i) {
				auto p = _Myptr()[i];
				h = 31 * h + p;
			}

			_hash = h;
		}
		return h;
	}

	//将字符串转为数字  
	//base:进制数。可以为8,10,16，如果其它值则强制为10。浮点数则忽略此参数
	template<typename T>
	T to_number(int base = 10) const
	{
		T t = T();
		_STD basic_stringstream<_Elem, _Traits, _Ax> ss(_Myptr());
		return conver_to_number<_Elem, _Traits, _Ax>(ss, t, base);
	}

	//将整数转化为字符串  
	//base:进制数。可以为8,10,16，如果其它值则强制为10  
	template<typename T>
	static _Myt from_number(T number, int base = 10)
	{
		_STD basic_stringstream<_Elem, _Traits, _Ax> ss;
		ss.setf(base_flag(base), _STD ios_base::basefield);
		ss << number;
		return ss.str();
	}

	//将float转化为字符串  
	//f:格式化参数。可以为'f','e','E','g','G'。'f'为定点数,'e'或'E'表示科学计数法  
	//  'g'或‘G’表示格式化为定点数或科学计数法，看哪一个表示方便。  
	//prec:小数点后的位数(定点数表示法)或总的有效位数(科学计数法)  
	static _Myt from_number(float number, _Elem f = _Elem('g'), int prec = 6)
	{
		return from_number(static_cast<double>(number), f, prec);
	}

	//将double转化为字符串，参数解释同上  
	static _Myt from_number(double number, _Elem f = _Elem('g'), int prec = 6)
	{
		basic_stringstream<_Elem, _Traits, _Ax> ss;
		ss << setprecision(prec);
		if (_Traits::eq(f, _Elem('f')))
		{
			ss << setiosflags(ios_base::fixed);
		}
		else if (_Traits::eq(f, _Elem('e')) || _Traits::eq(f, _Elem('E')))
		{
			ss << setiosflags(ios_base::scientific);
		}
		ss << number;
		return ss.str();
	}

	//将szFormat格式化为字符串，参数解释同sprintf  
	void format(const _Elem* szFromat, ...)
	{
		if (!szFromat)
			return;
		va_list argList;
		va_start(argList, szFromat);
		formatV(szFromat, argList);
		va_end(argList);
	}

	//将szFormat格式化为字符串，参数解释同sprintf  
	void formatV(const _Elem* szFormat, va_list argList)
	{
		if (!szFormat)
			return;
		int nLength = _ExTraits::ct_vscprintf(szFormat, argList);
		if (nLength < 0)
			return;
		resize(nLength);
		_ExTraits::ct_vspringf_s(_Myptr(), nLength + 1, szFormat, argList);
		va_end(argList);
	}
};


using string = base_string<char, ::std::char_traits<char>, ::std::allocator<char>, vl_char_traits<char>>;
using wstring = base_string<wchar_t, ::std::char_traits<wchar_t>, ::std::allocator<wchar_t>, vl_char_traits<wchar_t>>;

#ifdef _UNICODE
using tstring = base_string<wchar_t, ::std::char_traits<wchar_t>, ::std::allocator<wchar_t>, vl_char_traits<wchar_t>>;
#define tto_string  to_wstring 
#define tcout wcout
#else
using tstring = base_string<char, ::std::char_traits<char>, ::std::allocator<char>, vl_char_traits<char>>;
#define tto_string  to_string 
#define tcout cout
#endif

NS_CR_END

_STD_BEGIN

template<class _Elem,
	class _Traits,
	class _Alloc,
	class _ExTraits>
	struct hash<NS_CR base_string<_Elem, _Traits, _Alloc, _ExTraits>>
{
	size_t operator() (const NS_CR base_string<_Elem, _Traits, _Alloc, _ExTraits>& _Keyval) const NOEXCEPT
	{
		return 0;// (_Hash_array_representation(_Keyval.c_str(), _Keyval.size()));
	}
};

_STD_END



#endif // !_CR_TR1_STRING_

